package cn.baddonkey.photography.agent.utils;

import com.alibaba.fastjson.JSON;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.UploadResult;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.transfer.TransferManager;
import com.qcloud.cos.transfer.Upload;
import com.tencent.cloud.CosStsClient;
import com.tencent.cloud.Response;
import com.tencentcloudapi.cdn.v20180606.CdnClient;
import com.tencentcloudapi.cdn.v20180606.models.PurgeUrlsCacheRequest;
import com.tencentcloudapi.cdn.v20180606.models.PurgeUrlsCacheResponse;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.util.TreeMap;

/**
 * 腾讯云COS工具类
 */
@Component
@Slf4j
public class COSUtils {

    // 腾讯云 SecretId
    @Value("${cos.secretId}")
    private String SecretId;

    // 腾讯云 SecretKey
    @Value("${cos.secretKey}")
    private String SecretKey;

    // 临时密钥有效时长，单位是秒，默认1800秒，目前主账号最长2小时（即7200秒），子账号最长36小时（即129600秒）
    public static final Integer durationSeconds = 1800;

    //存储桶 bucket
    @Value("${cos.bucket}")
    private String bucket;

    //储存桶所在地区
    @Value("${cos.region}")
    private String region;

    @Value("${cdn.url}")
    private String cdnUrl;

    /**
     * 获取临时秘钥
     */
    public Response getTempSecret() {
        TreeMap<String, Object> config = new TreeMap<String, Object>();
        try {
            // 替换为您的 SecretId
            config.put("SecretId", SecretId);
            // 替换为您的 SecretKey
            config.put("SecretKey", SecretKey);

            // 临时密钥有效时长，单位是秒，默认1800秒，目前主账号最长2小时（即7200秒），子账号最长36小时（即129600秒）
            config.put("durationSeconds", durationSeconds);

            // 换成您的 bucket
            config.put("bucket", bucket);
            // 换成 bucket 所在地区
            config.put("region", region);

            // 这里改成允许的路径前缀，可以根据自己网站的用户登录态判断允许上传的具体路径，例子：a.jpg 或者 a/* 或者 * 。
            // 如果填写了“*”，将允许用户访问所有资源；除非业务需要，否则请按照最小权限原则授予用户相应的访问权限范围。
            config.put("allowPrefixes", new String[] {
                    "*"
            });

            // 密钥的权限列表。必须在这里指定本次临时密钥所需要的权限。
            // 简单上传、表单上传和分片上传需要以下的权限，其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
            String[] allowActions = new String[] {
                    // 简单上传
                    "name/cos:PutObject"
//                    // 表单上传、小程序上传
//                    "name/cos:PostObject",
//                    // 分块上传
//                    "name/cos:InitiateMultipartUpload",
//                    "name/cos:ListMultipartUploads",
//                    "name/cos:ListParts",
//                    "name/cos:UploadPart",
//                    "name/cos:CompleteMultipartUpload"
            };
            config.put("allowActions", allowActions);

            Response response = CosStsClient.getCredential(config);

            return response;
            //成功返回临时密钥信息，如下打印密钥信息
//            System.out.println(Jackson.toJsonPrettyString(response));
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("no valid secret !");
        }
    }

    public String upload(InputStream inputStream, String key) {
        TransferManager transferManager = createTransferManager();
        ObjectMetadata objectMetadata = new ObjectMetadata();
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, key, inputStream, objectMetadata);
        try {
            // 高级接口会返回一个异步结果Upload
            // 可同步地调用 waitForUploadResult 方法等待上传完成，成功返回 UploadResult, 失败抛出异常
            Upload upload = transferManager.upload(putObjectRequest);
            UploadResult uploadResult = upload.waitForUploadResult();
            return cdnUrl + key;
        } catch (CosClientException | InterruptedException e) {
            e.printStackTrace();
            throw new RuntimeException("upload failed");
        }
    }

    // 创建 TransferManager 实例，这个实例用来后续调用高级接口
    TransferManager createTransferManager() {
        // 创建一个 COSClient 实例，这是访问 COS 服务的基础实例。
        // 详细代码参见本页: 简单操作 -> 创建 COSClient
        COSClient cosClient = createCOSClient();
        // 传入一个 threadpool, 若不传入线程池，默认 TransferManager 中会生成一个单线程的线程池。
        TransferManager transferManager = new TransferManager(cosClient);
        return transferManager;
    }

    // 创建 COSClient 实例，这个实例用来后续调用请求
    COSClient createCOSClient() {
        // 设置用户身份信息。
        // SECRETID 和 SECRETKEY 请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi 进行查看和管理
        COSCredentials cred = new BasicCOSCredentials(SecretId, SecretKey);

        // ClientConfig 中包含了后续请求 COS 的客户端设置：
        ClientConfig clientConfig = new ClientConfig();

        // 设置 bucket 的地域
        // COS_REGION 请参见 https://cloud.tencent.com/document/product/436/6224
        clientConfig.setRegion(new Region(region));

        // 设置请求协议, http 或者 https
        // 5.6.53 及更低的版本，建议设置使用 https 协议
        // 5.6.54 及更高版本，默认使用了 https
        clientConfig.setHttpProtocol(HttpProtocol.https);


        // 生成 cos 客户端。
        return new COSClient(cred, clientConfig);
    }



    public void refreshCDN(String[] urls) throws TencentCloudSDKException {
        Credential cred = new Credential(SecretId, SecretKey);
        CdnClient cdnClient = new CdnClient(cred, region);
        PurgeUrlsCacheRequest purgeUrlsCacheRequest = new PurgeUrlsCacheRequest();
        purgeUrlsCacheRequest.setUrls(urls);
        PurgeUrlsCacheResponse response = cdnClient.PurgeUrlsCache(purgeUrlsCacheRequest);
        log.info("刷新cdn返回：", JSON.toJSONString(response));
    }

}
